package cn.zhaoyuening.fanrpc.consumer.core;

import cn.zhaoyuening.fanrpc.common.beans.RpcRequest;
import cn.zhaoyuening.fanrpc.common.beans.RpcResponce;
import cn.zhaoyuening.fanrpc.common.beans.RpcServiceAddress;
import cn.zhaoyuening.fanrpc.common.beans.ServiceBean;
import cn.zhaoyuening.fanrpc.common.utils.FanRpcUtils;
import cn.zhaoyuening.fanrpc.common.utils.JsonUtils;
import org.apache.curator.framework.CuratorFramework;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Set;

public class RpcClient implements ApplicationContextAware,InitializingBean{

    @Autowired
    private RpcClientInfo rpcClientInfo;
    @Autowired
    CuratorFramework zkClient;

    private ConfigurableApplicationContext applicationContext;
    //保存所有需要连接的服务提供者地址
    private Set<RpcServiceAddress> addressSet = new HashSet<RpcServiceAddress>();
    private RpcRequestSender requestSender = new RpcRequestSender();

    public void afterPropertiesSet() throws Exception {
        //获取服务提供者地址
        for (ServiceBean service :
                rpcClientInfo.getRpcServiceSet()) {
            byte[] bytes = zkClient.getData().forPath(FanRpcUtils.classVersionToServiceName(service.getZlass(), service.getVersion()));
            RpcServiceAddress address = JsonUtils.jsonToPojo(new String(bytes), RpcServiceAddress.class);
            addressSet.add(address);
            service.setRpcServiceAddress(address);
        }

        //与服务提供者建立连接
        requestSender.start();

        //对服务进行动态代理
        for (final ServiceBean service :
                rpcClientInfo.getRpcServiceSet()) {
            final String zlassName = service.getZlass();
            Class<?> zlass = Class.forName(zlassName);
            Object proxy = Proxy.newProxyInstance(zlass.getClassLoader(), zlass.getInterfaces(), new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    RpcRequest request = new RpcRequest()
                            .setMethod(method.getName())
                            .setParamTypes(method.getParameterTypes())
                            .setParam(args)
                            .setServiceName(zlassName)
                            .setVersion(service.getVersion());
                    RpcResponce responce = requestSender.sendRequest(service.getRpcServiceAddress(), request);
                    if (responce.getError() != null) {
                        throw responce.getError();
                    }
                    return responce.getResult();
                }
            });
            //将代理对象放入Spring容器中
            applicationContext
                    .getBeanFactory()
                    .registerResolvableDependency(zlass,proxy);
        }




    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }
}
